<?php
require_once 'lib/share/Snoopy.class.php';
require_once '../util/webmethod.lib.php';

/** 
 * 当当网[简称dangdang]API参数到网店,得到相应返回值。
 * @author alex  
 * @version v1.0  2010-8-31
 */
class DangDangRequest {
	/**
	 * @var string $host_url dangdang API的网站地址
	 */	
	var $_host_url='http://api.dangdang.com/';
	
	/**
	 * @var array $app_token 应用app访问dangdang的令牌，参数包括：<br/>
	 * string app_key :必须，后台设置的key值，将相关参数通过md5值<br/>
	 * string app_shopid :必须，商家在当当网开店的店铺编号。
	 */
	var $app_token=array();
	
	/**
	 * @var array $app_setting 应用app访问taobao的通用参数设置，一般不改变默认值<br/>
	 */
	var $app_setting=array();
	 
	/**
	 *  @var string $url 上次调用API接口的URL.
	 */
	var $url;
	
	/**
	 * @var int HTTPMETHOD_POST $httpmethod使用POST方法传递API参数，$httpmethod默认使用HTTPMETHOD_POST
	 */ 
	const  HTTPMETHOD_POST=0; 
	/**
	 * @var int HTTPMETHOD_POST $httpmethod使用GET方法传递API参数
	 */ 	
	const  HTTPMETHOD_GET=1;
	/**
	 * @var int HTTPMETHOD_POSTWITHFILE $httpmethod使用POST方法传递API参数，并且还要上传文件<br/>
	 * 如上传图像，array('image' => '/tmp/cs.jpg')
	 */ 		
	const  HTTPMETHOD_POSTWITHFILE=2;
	/**
	 * 
	 * @var int $httpmethod 传递API参数的方法，其值是：@see HTTPMETHOD_POST,@see HTTPMETHOD_GET,@see HTTPMETHOD_POSTWITHFILE <br/>
	 * 默认为HTTPMETHOD_POST，如果参数不合法，使用HTTPMETHOD_POST。
	 */
	var $httpmethod=0;
	/**
	 * @var array $postWithFiles 当$httpmethod=HTTPMETHOD_POSTWITHFILE时，使用此参数设置的文件上传<br/>
	 * 如上传图像，array('image' => '/tmp/cs.jpg')
	 */
	var $postWithFiles=array();
	
    function __construct($app_token=NULL){
    	$this->httpmethod=self::HTTPMETHOD_GET;
	    if(isset($app_token) && is_array($app_token))
	        $this->app_token=$app_token;
    }
	/**
	 * 得到dangdang API的返回XML字符串。
	 * @param string $cmdid 要调用的api接口的cmdid字符串，如user.getUserInfo，如果为空，将返回false.
	 * @param array $paramArr 要调用的api接口的参数数组，一般通用的参数不要传，如charset，format等。
	 * @return string|bool 调用的api接口得到的JSON,XML字符串。
	 */
	function &get($cmdid,array $paramArr){
		if(! $cmdid) return false; 
		if(! $this->app_token['app_shopid'] || ! $this->app_token['app_key']) 
		   return false;
		$cmdurl=str_replace('.','/',$cmdid).'.php';
		
		//组装url,param array.
		$paramArr=$paramArr + $this->app_setting;
		$paramArr['gShopID']=$this->app_token['app_shopid'];		
		$paramArr['validateString']=$this->_createSign($paramArr);

		$this->url = $this->_host_url . $cmdurl;
		
		//call taobao method
        $snoopy = new Snoopy();
        $snoopy->accept='text/xml';
        if($this->httpmethod == self::HTTPMETHOD_POST)
          $snoopy->submit($this->url,$this->_prepareParam($paramArr)); 
        elseif ($this->httpmethod == self::HTTPMETHOD_GET){
          $this->url .= '?' . $this->_createStrParam($paramArr);      
          $snoopy->fetch($this->url);
        }
        elseif ($this->httpmethod== self::HTTPMETHOD_POSTWITHFILE 
               && count($this->postWithFiles)>0){
          $snoopy->_submit_type='multipart/form-data';
          $snoopy->submit($this->url,$this->_prepareParam($paramArr),$this->postWithFiles);
        }
        else 
          $snoopy->submit($this->url,$this->_prepareParam($paramArr)); 
        
        if($snoopy->error)
          throw new Exception($snoopy->error);
        return $snoopy->results;
	}
	
	/**
	 * 得到 API的返回XML生成的数组。
	 * @param string $cmdid 要调用的api接口的cmdid字符串，如果为空，将返回false.
	 * @param array $paramArr 要调用的api接口的参数数组，一般通用的参数不要传，如gShopID，Key等。
	 * @return array|bool 调用的api接口得到的 XML生成的数组。
	 */	
	function &getArray($cmdid,array $paramArr){
		//parse xml format
		$result=&$this->get($cmdid,$paramArr);
		$result=preg_replace(array('/><!\[CDATA\[(.+)\]\]><\//'),'>${1}</',$result); //for some func value use CDATA  
		$result=str_replace('&','&amp;',$result);
		$arr=array(); 
		if(!webmethod_xml2array($result,$arr)) return false;
		if(!array_key_exists('response',$arr)) return false;
		$arr=$arr['response'];
		if(array_key_exists('functionID',$arr)) unset($arr['functionID']);
		if(array_key_exists('time',$arr)) unset($arr['time']);
		return $arr;
	}	
	
	/**
	 * 检查接口调用get*函数返回是否有错误
	 * @param  mixed $result  接口调用get*函数返回值.
	 * @return bool true 接口调用有效，false 接口调用出错.
	 */
	function checkResult(&$result,&$errorCode,&$errorMsg){
		$errorCode=0;
		$errorMsg=''; 		
		if(is_array($result)){
                if(! array_key_exists('Error',$result))
			          return true;				
				$error=$result['Error'];
				$errorCode=$error['operCode'];
				$errorMsg=$error['operation'];
		}
		elseif(is_bool($result))
		 return $result;

		return false;
	}

	/*
	 * 组参函数 ,内部用
	 */
	private function _createStrParam(array &$paramArr) {
		$strParam = '';
		foreach ( $paramArr as $key => $val ) {
			if ($key != '' && isset($val)) {
				if(is_array($val)) {
					if( count($val)>0)
					foreach ($val as $item)
					  $strParam .= $key . '=' . urlencode( $item ) . '&';
				}
				else 
				$strParam .= $key . '=' . urlencode( $val ) . '&';
			}
		}
		return $strParam;
	}	
	private function _prepareParam(array &$paramArr) { //trim empty value
		$Paramok =array();
		foreach ( $paramArr as $key => $val ) {
			if ($key != '' && isset($val)) {
				if(is_array($val)) {
					$itemarr=array();
					foreach ($val as $item)
					  if($item != '')  $itemarr[]=$item;
					$Paramok[$key] = $itemarr ;
				}
				else 
				$Paramok[$key] = $val; //Snoopy类在执行submit函数时，它自动会将参数做urlencode编码
			}
		}
		return $Paramok;
	}	
	/*
	 * 签名函数,内部用 
	 */
    private function _createSign(array $paramArr) {
		$sign = '';
		ksort ( $paramArr );
		foreach ( $paramArr as $key => $val ) {
			if ($key != '' && isset($val)) {
				if (is_array ( $val )) {
					if(count ( $val ) > 0)
					foreach ( $val as $item )
						$sign .=  $item;
				} 
				else
					$sign .= $val;
			}
		}	
		$app_key=$this->app_token['app_key'];
	    $sign = md5($sign . $app_key);
		return $sign;
	}
	
}

